package com.rainng.coursesystem.config;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 记录日志的类，目前只是记录error级别的日志，便于线上排查
 */
@Slf4j
@Aspect
@Component
public class InterfaceLogAspect {
     //记录运行过程中的报错日志
     @AfterThrowing(pointcut = "execution(* com.rainng.coursesystem.controller.admin.*.*(..))",throwing = "e")
     public void saveErrorLogInfo(JoinPoint joinPoint, Throwable e){
          Object[] args = joinPoint.getArgs();
          String errorParam=argsArrayToString(args);
          // 从切面织入点处通过反射机制获取织入点处的方法
          MethodSignature signature = (MethodSignature) joinPoint.getSignature();
          // 获取切入点所在的方法
          Method method = signature.getMethod();
          // 获取请求的类名
          String className = joinPoint.getTarget().getClass().getName();
          // 获取请求的方法名
          String methodName = method.getName();
          methodName = className + "." + methodName + "()";
          // 获取当前时间
          Date currentDate = new Date();
          SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          // 格式化日期
          String formattedDate = format.format(currentDate);
          String finalErrorMessage=stackTraceToString(formattedDate,methodName,errorParam,e.getStackTrace());
          log.error(finalErrorMessage);
     }

     /**
      * 转换异常信息为字符串
      */
     public String stackTraceToString(String formattedDate,String exceptionName, String exceptionMessage, StackTraceElement[] elements) {
          StringBuffer strbuff = new StringBuffer();
          for (StackTraceElement stet : elements) {
               strbuff.append(stet + "\n");
          }
          String message = "报错时间：" +formattedDate + "\n"+"报错方法：" +exceptionName + "\n"+ "报错入参：:" + exceptionMessage + "\n" + "报错详细信息：:"+ strbuff.toString();
          message = substring(message, 0, 200);
          return message;
     }


     //字符串截取
     public static String substring(String str, int start, int end) {
          if (str == null) {
               return null;
          } else {
               if (end < 0) {
                    end += str.length();
               }
               if (start < 0) {
                    start += str.length();
               }
               if (end > str.length()) {
                    end = str.length();
               }
               if (start > end) {
                    return "";
               } else {
                    if (start < 0) {
                         start = 0;
                    }

                    if (end < 0) {
                         end = 0;
                    }
                    return str.substring(start, end);
               }
          }
     }

     /**
      * 参数拼装
      */
     private String argsArrayToString(Object[] paramsArray) {
          String params = "";
          if (paramsArray != null && paramsArray.length > 0) {
               for (Object o : paramsArray) {
                    if (o != null) {
                         try {
                              Object jsonObj = JSON.toJSON(o);
                              params += jsonObj.toString() + " ";
                         } catch (Exception e) {
                              e.printStackTrace();
                         }
                    }
               }
          }
          return params.trim();
     }
}
